
// 装饰器语法，使用方式类似注解（@Components），在Angular2.0中它是一个函数
// 装饰器概念，最早见于Angular2.0中，是由Typesciprt实现的，而Javascript中开始是有装饰器提案的，只是一直未能通过，目前还是Stage-2 草案阶段
// 因此，在javascript中使用装饰器语法要借助两种方式：
// 1,使用babel;
// 2,使用typescript。需要在tsconfig.json 将 "experimentalDecorators" 设置为true
// 定义：一种与类相关的语法，用来注释或修改类和类的方法
// 通俗理解：一种方法或特殊声明，可以注解在类、方法，属性、参数上来扩展其功能（在不改变其代码的情况下）
// 常用方式：注解在类、方法、属性、参数上
// 装饰器类型：普通装饰器（无法传参），装饰器工厂（可以传参）
// export module DecoratorSyntax {


// }


// #类装饰器：注解在类上

// 1，普通装饰器，无法传参
// function ApendSth(target: any) {
//     // console.log(target); //target
//     target.prototype.apiUrl = 'baidu.com'
//     target.prototype.sendData = function (): void {
//         console.log('数据已发送');
//     }
// }

// @ApendSth
// class HttpClient {
//     constructor() {
//     }
//     send() {
//     }
// }
// let l:any = new HttpClient();
// console.log(l.apiUrl);  //等同于 l.constructor.prototype.apiUrl
// l.sendData()
// // console.log(HttpClient.prototype);

// 2，装饰器工厂：可以传参
// function ApendSth(params: string) {
//     // target为所注解的类
//     return function (target: any) {
//         // console.log('params: ', params);
//         // console.log('target: ', target);
//         target.prototype.apiUrl=params;
//     }
// }

// // 装饰器工厂，可以传参
// @ApendSth('www.baidu.com')
// class HttpClient {
//     constructor() {
//     }
//     send() {
//     }
// }

// let l:any=new HttpClient();
// console.log(l.apiUrl);

// 3，重载类的构造函数(包括属性和方法)
// 类的构造函数作为其唯一的参数，如果装饰器返回一个值，它会使用提供的构造函数来替换类的声明
// function ApendSth(target: any) {
//     // target为所注解的类
//     return class extends target {
//         _apiUrl: any = 'baidu'
//         send() {
//             this._apiUrl = this._apiUrl + '.com'
//             console.log(this._apiUrl);
//         }
//     }
// }

// @ApendSth
// class HttpClient {
//     _apiUrl: string
//     constructor(url?: string) {
//         if (url)
//             this._apiUrl = url
//         else
//             this._apiUrl = '';
//     }

//     send() {
//         console.log(this._apiUrl);
//     }
// }
// let http = new HttpClient('传入一个url');
// http.send();

// #属性装饰器
// 需传入2个参数：
// 1，对于静态成员来说是类的构造函数，对于实例成员来说是类的原型对象
// 2，成员的名字

// function ApendSth(params: string) {
//     return function (target: any) {
//         console.log('这是类的装饰器 ' + params, target.prototype);
//     }
// }
// function propertyDec(params: any) {
//     return function (target: any, attr: any) {
//         console.log('params: ', params);    //装饰器传递过来的参数，在这里是[www.baidu.com]
//         console.log('target: ', target);    //这里的target 就是HttpClient的原型对象(实例原型)
//         console.log('attr: ', attr);        //所注入的属性名    
//         target[attr] = 'http://' + params;
//     }
// }

// @ApendSth('xxx')
// class HttpClient {
//     @propertyDec('www.baidu.com')
//     _apiUrl: any;

//     // @propertyDec('www.baidu.com')
//     // static common:any;

//     constructor() {
//     }

//     send() {
//         console.log('send: ', this._apiUrl);
//         // console.log('send: ', HttpClient.common);
//     }
// }
// let http = new HttpClient();
// http.send();


// #方法装饰器

/**
 * 它会被应用到方法的 属性描述符上，可以用来监视，修改或者替换方法定义。 
 * 方法装饰器不能用在声明文件( .d.ts)，重载或者任何外部上下文（比如declare的类）中。
 **/

/**
 * 方法装饰器表达式会在运行时当作函数被调用，传入下列3个参数：
 * 对于静态成员来说是类的构造函数，对于实例成员是类的原型对象。
 * 成员的名字。
 * 成员的属性描述符。 
 **/

// 方法装饰器1
// function getDec(params: any) {
//     return function (target: any, method: any, desc: any) {
//         console.dir(target);
//         console.dir(method);
//         console.dir(desc);

//         target.apiUrl = 'http://www.' + params
//         target.run = function () {
//             console.log('run');
//         }
//     }
// }

// class HttpClient {
//     url: any

//     constructor() { }
//     @getDec('baidu.com')
//     getData() {
//         console.log(this.url);
//     }
// }

// let http: any = new HttpClient();
// console.log(http.apiUrl);
// http.run();

// 方法装饰器2
// 作用：把装饰器方法里面传入的参数改为string类型
// function getDec(params: any) {
//     return function (target: any, method: any, desc: any) {
//         // console.dir(target);    //指向HttpClient
//         // console.dir(method);    //指向方法名getData
//         // console.dir(desc);      //指向getData()
//         let getFn = desc.value     //保存当前方法
//         desc.value = function (...args: any[]) {
//             args = args.map(value => { return String(value) })
//             getFn.apply(this, args)
//         }
//     }
// }

// class HttpClient {
//     url: any

//     constructor() { }
//     @getDec('baidu.com')
//     getData(...args: any[]) {
//         console.log(args);
//     }
// }

// let http: any = new HttpClient();
// http.getData(123, 'xx');

// #参数装饰器
/** 
    参数装饰器声明在一个参数声明之前（紧靠着参数声明）。 参数装饰器应用于类构造函数或方法声明。
    参数装饰器不能用在声明文件（.d.ts），重载或其它外部上下文（比如 declare的类）里。
    参数装饰器表达式会在运行时当作函数被调用，传入下列3个参数：
    对于静态成员来说是类的构造函数，对于实例成员是类的原型对象。
    成员的名字。
    参数在函数参数列表中的索引。
    注意  参数装饰器只能用来监视一个方法的参数是否被传入。
 */
// function paramsDec(params: any) {
//     return function (target: any, methodsName: any, paramsIndex: any) {
//         console.dir(target);         //指向HttpClient
//         console.dir(methodsName);    //指向方法名getData
//         console.dir(paramsIndex);    //指向所装饰的参数在参数列表中的索引
//         console.log(params);         //通过装饰器传入的参数       
//         target.apiUrl = 'www.baidu.com'
//     }
// }

// class HttpClient {
//     url: any
//     constructor() { }
//     getData(name: string, @paramsDec('4308') uuid: any) {
//         console.log('getData: ', uuid);
//     }
// }

// let http: any = new HttpClient();
// http.getData('小红', 1000);
// console.log(http.apiUrl);


// #装饰器执行顺序
/**
 * 属性>参数>方法>类
 * 同类型的装饰器，后面的先执行
 */
// function classDec1(params?:string) {
//     return function (target:any) {
//         console.log('类装饰器1');        
//     }
// }
// function classDec2(params?:string) {
//     return function (target:any) {
//         console.log('类装饰器2');        
//     }
// }
// function attrDec1(params?:any) {
//     return function (target:any,attrName:string) {
//         console.log('属性装饰器1');        
//     }
// }
// function attrDec2(params?:string) {
//     return function (target: any, attrName: string) {
//         console.log('属性装饰器2');        
//     }
// }
// function methodDec1(params?:string) {
//     return function (target:any,methodName:string,desc:any) {
//         console.log('方法装饰器1');        
//     }
// }
// function methodDec2(params?:string) {
//     return function (target:any,methodName:string,desc:any) {
//         console.log('方法装饰器2');        
//     }
// }
// function paramsDec1(params?:string) {
//     return function (target: any, methodName: string, paramsIndex: number) {
//         console.log('参数装饰器1');        
//     }
// }

// function paramsDec2(params?:string) {
//     return function (target: any, methodName: string, paramsIndex: number) {
//         console.log('参数装饰器2');        
//     }
// }

// @classDec1()
// @classDec2()
// class HttpClient {

//     @attrDec1()
//     @attrDec2()
//     url: any

//     constructor() { }

//     @methodDec1()
//     @methodDec2()
//     getData(@paramsDec1() name: string, @paramsDec2() uuid: any) {
//     }
// }

let arr: number[] = [3, 12, 9, 6, 8,]

// arr.sort((a,b)=>{
//     console.log(a,b);    
//     return b-a;
// });
// console.log(arr);


for (let i = 0; i < arr.length - 1; i++) {
    for (let j = 0; j < arr.length - 1; j++) {
        let min = arr[j];
        if (min > arr[j + 1]) {
            min = arr[j + 1];
            arr[j + 1] = arr[j]
            arr[j] = min;
        }
    }

}
console.log(arr);
